/*
 * clusters.c
 *
 *  Created on: 09/10/2011
 *      Author: Normandia
 */

#include "clusters.h"

uint32_t direc_cluster(uint64_t n_cluster) {

	// tamañoAreaReservados + tamañoFATRegion + (numeroDeCluster * tamañoCluster)
	return cache_boot_sector->n_reserved_sector +
			cache_boot_sector->n_sectors_per_fat * cache_boot_sector->n_fat+
			(n_cluster - 2) * cache_boot_sector->n_sectors_per_cluster;

}

void* leerCluster(uint32_t n_cluster) {

	void* cluster;
	uint32_t n_direc_cluster, i;
	uint8_t  n_cluster_size;
	n_direc_cluster = direc_cluster(n_cluster);
	n_cluster_size = cache_boot_sector->n_sectors_per_cluster;

	cluster = malloc(SECTOR_SIZE * n_cluster_size);

	for(i=0; i < n_cluster_size; i=i+BLOCK_SIZE) {
		readBlock(i+n_direc_cluster,cluster + i * SECTOR_SIZE);
	}

	return cluster;

}

void escribirCluster(uint32_t n_cluster, void* buf) {

	uint32_t n_direc_cluster, i;
	uint8_t  n_cluster_size;
	n_direc_cluster = direc_cluster(n_cluster);
	n_cluster_size = cache_boot_sector->n_sectors_per_cluster;

	for(i=0; i < n_cluster_size; i=i+BLOCK_SIZE) {
		writeBlock(i+n_direc_cluster, buf+i*SECTOR_SIZE);
	}

}

uint32_t obtenerSigCluster(uint32_t n_cluster) {

	return cache_fat[n_cluster];

}

uint32_t obtenerNCluster(uint32_t primer_cluster, uint32_t i) {

	uint32_t j;
	uint32_t cluster;

	cluster = primer_cluster;

	for (j = 0; j < i; j++) {

		cluster = cache_fat[cluster];

		if (cluster >= DT_FILENAME_EOC)
			break;
	}

	return cluster;

}

/*
uint32_t obtenerProxClusterLibre(){

	while(cache_fat[cache_boot_sector->ultimo_cluster_aloc] != 0){

		cache_boot_sector->ultimo_cluster_aloc;

		// Si llegamos al tope, vuelve al principio.
		if(cache_boot_sector->ultimo_cluster_aloc
			> cache_boot_sector->n_sectors_ext
				/ cache_boot_sector->n_sectors_per_cluster) {

			cache_boot_sector->ultimo_cluster_aloc = 0;

		}

	}
	return cache_boot_sector->ultimo_cluster_aloc;

}
*/
uint32_t reservarCluster(uint32_t primer_cluster) {

	uint32_t nuevo_cluster;
	NODELIBREPTR data;

	while(obtenerSigCluster(primer_cluster) < 0x0FFFFFF0)
		primer_cluster = obtenerSigCluster(primer_cluster);

	data = (NODELIBREPTR) collection_queue_pop(ptrListaSectLibre);
	nuevo_cluster = data->n_cluster;
	free(data);

	cache_fat[primer_cluster] = nuevo_cluster;
	cache_fat[nuevo_cluster] = CLUSTER_EOF;

	return nuevo_cluster;

}

NODELIBREPTR  addNodo(NODELIBREPTR sPtr,uint64_t i){

        NODELIBREPTR nPtr,pPtr,cPtr;

        nPtr =  malloc(sizeof(LISTNODELIBRE));

        if(sPtr == NULL || (sPtr)->n_cluster > i){

                nPtr->n_cluster =  i;

                nPtr->nextPtr = sPtr;
                sPtr = nPtr;
                //printf("El valor de sPtr es :%u\n",sPtr->n_cluster);
        }else{
                pPtr = NULL;
                cPtr = sPtr;

                while(cPtr != NULL && i >cPtr->n_cluster){
                        pPtr = cPtr;
                        cPtr = cPtr->nextPtr;
                }
                nPtr->n_cluster =  i;
                if(pPtr == NULL){

                        nPtr->nextPtr = cPtr;
                        sPtr = nPtr;
                }else{
                        pPtr->nextPtr = nPtr;
                        nPtr->nextPtr = cPtr;
                }
        }
        printf("Insertado valor %u\n",nPtr->n_cluster);
        return sPtr;

}

NODELIBREPTR ObtenerUltimoNodo(NODELIBREPTR cPtr){
	if(cPtr == NULL){
		return NULL;
	}else{
		while(cPtr->nextPtr != NULL){
			cPtr = cPtr->nextPtr;
		}
		return cPtr;
	}
}

NODELIBREPTR addAListaDeCluster(NODELIBREPTR sPtr,NODELIBREPTR  ptr){

	if(ptr == NULL){
		return NULL;
	}

	NODELIBREPTR ptrLibre;
	ptrLibre = ObtenerUltimoNodo(sPtr);
	if(ptrLibre == NULL){
		sPtr = ptr;
	}else{
		ptrLibre->nextPtr = ptr;
	}
	printf("cluster: %u\n",ptrLibre->n_cluster);
	return sPtr;
}


void mostrarLista(NODELIBREPTR cPtr){
	if(cPtr == NULL){
		printf("La está vacía.\n\n");
	}else{
		printf("La lista es: \n");
		while(cPtr != NULL){
			printf("El valor de la lista es: %u\n", cPtr->n_cluster);
			cPtr = cPtr->nextPtr;
		}
		printf("\n\n");
	}

}

void destructor_cluster(void* cluster){

	//((NODELIBREPTR) cluster)->n_cluster = NULL;
	free(cluster);

}

/*

clusterLibre* ObtenerUltimoNodo(clusterLibre* cPtr){
	if(cPtr == NULL){
		return NULL;
	}else{
		while(cPtr->nextPtr != NULL){
			cPtr = cPtr->nextPtr;

		}
		return cPtr;
	}
}

void addAListaDeCluster(clusterLibre *sPtr,clusterLibre  *ptr){

	if(ptr == NULL){
		return ;
	}

	clusterLibre *ptrLibre;
	ptrLibre = ObtenerUltimoNodo(sPtr);
	if(ptrLibre== NULL){
		sPtr = ptr;
	}else{
		ptrLibre->nextPtr = ptr;
	}
}

void eliminarClusters(clusterLibre *ptr,uint64_t n_cluster){

	clusterLibre nPtr,cPtr,tPtr;

	if(ptr== NULL){
		return;
	}

	if(ptr->n_cluster == n_cluster){
		nPtr = *ptr;
		*ptr = (*ptr)->nextPtr;
		free(nPtr);
	}else{

		cPtr = *ptr;
		tPtr= (*ptr)->nextPtr;

		while(tPtr != NULL && tPtr->n_cluster != n_cluster){
			cPtr = *tPtr;
			tPtr = tPtr->nextPtr;
		}

		if(tPtr == NULL){
			return ;
		}else{
			cPtr->nextPtr = tPtr->nextPtr;
			free(tPtr);
		}
	}
}
*/
/*
void addNodo(LISTNODEPTR *sPtr,char value){
	LISTNODEPTR nPtr,pPtr,cPtr;

	nPtr =  malloc(sizeof(LISTNODE));
	if(nPtr != NULL){
		nPtr->data =  value;
		nPtr->nextPtr = NULL;

		pPtr = NULL;
		cPtr = *sPtr;

		while(cPtr != NULL && value > cPtr->data){
			pPtr = cPtr;
			cPtr = cPtr->nextPtr;
		}

		if(pPtr == NULL){
			nPtr->nextPtr = cPtr;
			*sPtr = nPtr;
		}else{
			pPtr->nextPtr = nPtr;
			nPtr->nextPtr;
		}
	}else{
		printf("%c not inserted. No memory available.\n", value);
	}
}

char eliminarNodo(LISTNODEPTR *sPtr,char value){
	LISTNODEPTR pPtr,cPtr,tPtr;

	if(value == (*sPtr)->data){
		tPtr = *sPtr;
		*sPtr = (*sPtr)->nextPtr;
		free(tPtr);
		return value;
	}else{
		pPtr = *sPtr;
		cPtr= (*sPtr)->nextPtr;

		while(cPtr != NULL && cPtr->data != value){
			pPtr = cPtr;
			cPtr = cPtr->nextPtr;
		}

		if(cPtr != NULL){
			tPtr = cPtr;
			pPtr->nextPtr = cPtr->nextPtr;
			free(tPtr);
			return value;

		}
	}
	return '\0';
}

int listaVacia(LISTNODEPTR sPtr){
	return (sPtr == NULL);
}

void mostrarLista(LISTNODEPTR cPtr){
	if(cPtr == NULL){
		printf("La lista está vacía.\n\n");
	}else{
		printf("La lista es: \n");
		while(cPtr != NULL){
			printf("%c",cPtr->data);
			cPtr = cPtr->nextPtr;
		}
		printf("\n\n");
	}

}
*/

